package controller

import (
	"blog_server/model"
	"blog_server/utils"
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"strconv"
)

func AddComment(c *gin.Context) {
	db := model.GetDB()
	articleID, _ := strconv.Atoi(c.Param("id"))
	user, _ := c.Get("user")

	var commentReq model.CommentRequest
	if err := c.ShouldBind(&commentReq); err != nil {
		utils.Fail(c, nil)
		return
	}

	comment := model.Comment{
		Content:   commentReq.Content,
		UserId:    user.(model.User).ID,
		ArticleId: uint(articleID),
		Likes:     0,
		FatherId:  0,
	}

	if err := db.Create(&comment).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()})
		return
	}

	utils.Success(c, nil)
}

func DeleteComment(c *gin.Context) {

}

func ShowCommentsCount(c *gin.Context) {
	db := model.GetDB()
	articleID, _ := strconv.Atoi(c.Param("id"))
	var count int64

	db.Model(&model.Comment{}).Where("article_id = ?", articleID).Count(&count)

	utils.Success(c, gin.H{"count": count})
}

func ShowComment(c *gin.Context) {
	db := model.GetDB()
	commentID, _ := strconv.Atoi(c.Param("id"))
	var comment model.CommentInfo

	db.Model(&model.Comment{}).
		Select("comments.id, comments.content, comments.user_id, comments.article_id, "+
			"users.user_name, users.avatar, comments.created_at, comments.likes").
		Joins("left join users on comments.user_id = users.id").
		Where("comments.id = ?", commentID).
		Find(&comment)

	utils.Success(c, gin.H{"comment": comment})
}

func ShowCommentList(c *gin.Context) {
	db := model.GetDB()
	articleID, _ := strconv.Atoi(c.Param("id"))
	var commentList []model.CommentInfo
	var count int64

	fmt.Println(articleID)

	db.Model(&model.Comment{}).
		Select("comments.id, LEFT(comments.content,100) AS content, comments.user_id, comments.article_id, "+
			"users.user_name, users.avatar, comments.created_at, comments.likes").
		Joins("left join users on comments.user_id = users.id").
		Where("comments.article_id = ? and comments.father_id = 0", articleID).
		Scan(&commentList)

	query := `
		WITH RECURSIVE subcomments(id, father_id) AS (
				SELECT id, father_id
				FROM comments
				WHERE father_id = ?
			UNION
				SELECT comments.id, subcomments.father_id
				FROM comments, subcomments
				WHERE comments.father_id = subcomments.id
		)
		SELECT *
		FROM subcomments;
	`

	for index, comment := range commentList {
		commentId := comment.ID
		var subcommentList []model.SubComment
		var replies uint
		if err := db.Raw(query, commentId).Scan(&subcommentList).Error; err != nil {
			c.JSON(http.StatusOK, gin.H{"code": 400, "msg": "executing error recursive query!"})
			return
		}
		replies = uint(len(subcommentList))
		commentList[index].ReplyCnt = uint(replies)
	}

	db.Model(&model.Comment{}).Where("article_id = ?", articleID).Count(&count)
	fmt.Println(count)

	utils.Success(c, gin.H{"comments": commentList, "count": count})
}

func AddReply(c *gin.Context) {
	db := model.GetDB()
	articleId, _ := strconv.Atoi(c.Param("id"))
	user, _ := c.Get("user")

	var replyReq model.ReplyRequest
	if err := c.ShouldBind(&replyReq); err != nil {
		utils.Fail(c, nil)
		return
	}

	var replyComment = model.Comment{
		Content:   replyReq.Content,
		UserId:    user.(model.User).ID,
		FatherId:  replyReq.FatherId,
		Likes:     0,
		ArticleId: uint(articleId),
	}

	if err := db.Create(&replyComment).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()})
		return
	}

	utils.Success(c, nil)
}

func ShowReplyList(c *gin.Context) {
	db := model.GetDB()
	commentId, _ := strconv.Atoi(c.Param("id"))
	var replyList []model.SubCommentInfo
	var count int64

	query := `
		WITH RECURSIVE subcomments(id, father_id) AS (
				SELECT id, father_id
				FROM comments
				WHERE father_id = ?
			UNION
				SELECT comments.id, subcomments.father_id
				FROM comments, subcomments
				WHERE comments.father_id = subcomments.id
		)
		SELECT *
		FROM subcomments;
	`

	var subcommentList []model.SubComment
	if err := db.Raw(query, commentId).Scan(&subcommentList).Error; err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 400, "msg": "executing error recursive query!"})
		return
	}

	for _, subcomment := range subcommentList {
		subId := subcomment.Id
		var comment model.Comment
		if err := db.Where("id = ?", subId).Find(&comment).Error; err != nil {
			c.JSON(http.StatusOK, gin.H{"code": 400, "msg": "find current comment failed!"})
			return
		}
		parentId := comment.FatherId
		var parentComment model.Comment
		if err := db.Where("id = ?", parentId).Find(&parentComment).Error; err != nil {
			c.JSON(http.StatusOK, gin.H{"code": 400, "msg": "find parent comment failed!"})
			return
		}

		var replyer model.UserInfo
		if err := db.Model(&model.User{}).
			Select("id, avatar, user_name").
			Where("id = ?", comment.UserId).
			Find(&replyer).
			Error; err != nil {
			c.JSON(http.StatusOK, gin.H{"code": 400, "msg": "find replyer failed!"})
			return
		}

		var replied model.UserInfo
		if err := db.Model(&model.User{}).
			Select("id, avatar, user_name").
			Where("id = ?", parentComment.UserId).
			Find(&replied).
			Error; err != nil {
			c.JSON(http.StatusOK, gin.H{"code": 400, "msg": "find replied failed!"})
			return
		}

		replyInfo := model.SubCommentInfo{
			ID:            comment.ID,
			Content:       comment.Content,
			UserId:        replyer.ID,
			ArticleId:     comment.ArticleId,
			UserName:      replyer.UserName,
			Avatar:        replyer.Avatar,
			CreatedAt:     comment.CreatedAt,
			Likes:         comment.Likes,
			FatherId:      comment.FatherId,
			RepliedId:     replied.ID,
			RepliedAvatar: replied.Avatar,
			RepliedName:   replied.UserName,
		}

		replyList = append(replyList, replyInfo)
	}

	count = int64(len(replyList))

	utils.Success(c, gin.H{"replies": replyList, "count": count})
}
